package com.gopay.scheduler.service.fund.impl;

import com.gopay.common.constants.cust.CustCorpInfoConstants;
import com.gopay.common.constants.fund.FundFilePathEnum;
import com.gopay.common.constants.fund.FundFileTypeEnum;
import com.gopay.common.constants.fund.FundSettleStatusEnum;
import com.gopay.common.constants.trans.TxnStaCode;
import com.gopay.common.cps.dao.fund.FundFileDao;
import com.gopay.common.domain.fund.FundGopayCpsGenOrder;
import com.gopay.common.domain.fund.FundGopayFileEntity;
import com.gopay.common.order.dao.CommonQueryDAO;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.FastJsonUtil;
import com.gopay.common.util.ReadFundZipUtils;
import com.gopay.common.util.SftpUtil;
import com.gopay.scheduler.dao.BaseOperateDao;
import com.gopay.scheduler.service.fund.FundBaseOperateService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;


@Service
public class FundBaseOperateServiceImpl implements FundBaseOperateService {
    /**
     * logger
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(FundBaseOperateServiceImpl.class);

    private @Value("#{ webProperties['fund.sftp.host'] }")
    String IP;
    private @Value("#{ webProperties['fund.sftp.port'] }")
    Integer PORT;
    private @Value("#{ webProperties['fund.sftp.name'] }")
    String USERNAME;
    private @Value("#{ webProperties['fund.sftp.pwd'] }")
    String PASSWORD;
    private @Value("#{ webProperties['fund.sftp.timeout'] }")
    Integer TIMEOUT;
    private ResourceBundle bundle = ResourceBundle.getBundle("fund");
    @Resource(name = "commonQueryDAO")
    private CommonQueryDAO commonQueryDAO;
    @Resource(name = "baseOperateCornDao")
    private BaseOperateDao operateDao;
    @Resource(name = "fundFileDao")
    private FundFileDao fundFileDao;

    /**
     * 查询所有基金用户
     *
     * @return java.util.List<java.lang.String>
     * @author dong-wang5@hnair.com
     * @date 2017-11-10 13:15:45
     * @params
     */
    @Override
    public List<String> queryAllFundCorp() {
        List<String> merchantIds = new ArrayList<>();
        StringBuffer sb = new StringBuffer();
        sb.append(" select corp.cust_id,corp.corp_name from CUST_CORP_INFO corp ,CUST_INFO_EXTEND_ITEM item where corp.cust_id= item.cust_id and item.item_key='fundOrgNo' ");
        List<Object[]> rsList = commonQueryDAO.findBySql(sb.toString());
        if (rsList != null && rsList.size() > 0) {
            for (Object[] obj : rsList) {
                merchantIds.add(obj[0].toString());
            }
        }
        return merchantIds;
    }

    @Override
    public List<FundGopayCpsGenOrder> query02018FundOrderProcessing() {
        List<FundGopayCpsGenOrder> orderList = new ArrayList<>();
        StringBuffer sb = new StringBuffer();
        sb.append("SELECT STLM_DATE,GOPAY_ORDER_ID FROM FUND_GOPAY_CPS_GEN_ORDER WHERE ORDER_TYPE =:orderType AND GOPAY_INT_TXN_CD='02018'");
        Map<String, Object> map = new HashMap<>();
        map.put("orderType", FundSettleStatusEnum.PAY_LOADING.getValue());
        List<Object[]> rsList = commonQueryDAO.findBySql(sb.toString(), map);
        if (rsList != null && rsList.size() > 0) {
            for (Object[] obj : rsList) {
                FundGopayCpsGenOrder fundOrder02018 = new FundGopayCpsGenOrder();
                if (null == obj[0] || null == obj[1]) {
                    continue;
                }
                fundOrder02018.setStlmDate((Date) obj[0]);
                fundOrder02018.setGopayOrderId(obj[1].toString());
                orderList.add(fundOrder02018);
            }
        }
        return orderList;
    }
//    @Override
//    public List<FundGopayCpsGenOrder> queryFundOrderProcessing(String gopayOrderId, String intTxnCd, String ordertype, String memo) {
//        List<FundGopayCpsGenOrder> orderList = new ArrayList<>();
//        StringBuilder sb = new StringBuilder();
//        sb.append("SELECT STLM_DATE,GOPAY_ORDER_ID, MER_REMARK2 ,TOTAL_ORDER_AMT,MERCHANT_ID " +
//                " FROM  FUND_GOPAY_CPS_GEN_ORDER WHERE MER_REMARK2=:gopayOrderId AND GOPAY_INT_TXN_CD=:intTxnCd AND ORDER_TYPE=:orderType  AND MEMO=:processType  ");
//        Map<String, Object> map = new HashMap<>();
//        map.put("gopayOrderId", gopayOrderId);
//        map.put("intTxnCd", intTxnCd);
//        map.put("orderType", ordertype);
//        map.put("processType", memo);
//
//        List<Object[]> rsList = commonQueryDAO.findBySql(sb.toString(), map);
//        if (rsList != null && rsList.size() > 0) {
//            for (Object[] obj : rsList) {
//                FundGopayCpsGenOrder fundOrder = new FundGopayCpsGenOrder();
//                if (null == obj[0] || null == obj[1] || null == obj[2] || null == obj[3] || null == obj[4]) {
//                    continue;
//                }
//                fundOrder.setStlmDate((Date) obj[0]);
//                fundOrder.setGopayOrderId(obj[1].toString());
//                fundOrder.setMerRemark2(obj[2].toString());
//                fundOrder.setTotalOrderAmt(new BigDecimal(obj[3].toString()));
//                fundOrder.setMerchantId(obj[4].toString());
//                orderList.add(fundOrder);
//            }
//        }
//        return orderList;
//    }

    @Override
    public List<Map<String,String>> checkRedeemIsSuccess(String orderId){
        List<Map<String,String>> orderList = new ArrayList<>();
        Map<String, Object> map = new HashMap<>(2);
        StringBuffer successSql = new StringBuffer();
        successSql.append("SELECT GOPAY_ORDER_ID,ORDER_TYPE FROM FUND_GOPAY_CPS_GEN_ORDER" +
                "  WHERE GOPAY_INT_TXN_CD IN ('02012', '02014', '02015','02020','02021') AND ORDER_TYPE !=:status AND MER_REMARK2=:orderId");
        map.put("orderId", orderId);
        map.put("status", FundSettleStatusEnum.SUCCESS_SETTLE.getValue());
        List<Object[]> bySql = commonQueryDAO.findBySql(successSql.toString(), map);
        for (Object[] objects : bySql) {
            Map<String,String> resultMap = new HashMap<>();
            resultMap.put("gopayOrderId",objects[0].toString());
            resultMap.put("orderType",objects[1].toString());
            orderList.add(resultMap);
        }
        return orderList;
    }

//    @Override
//    public boolean queryAllRedeemOrder(String orderId, String status) {
//        Map<String, Object> map = new HashMap<>();
//        StringBuffer successSql = new StringBuffer();
//        successSql.append("SELECT count(1) " +
//                "  FROM FUND_GOPAY_CPS_GEN_ORDER " +
//                "  WHERE GOPAY_INT_TXN_CD IN ('02012', '02014', '02015','02020','02021') AND ORDER_TYPE !=:status AND MER_REMARK2=:orderId");
//        map.put("orderId", orderId);
//        map.put("status", status);
//        int countSuccess = commonQueryDAO.findCountBySql(successSql.toString(), map);
//        StringBuffer allSql = new StringBuffer();
//        allSql.append("SELECT count(1)  " +
//                "  FROM FUND_GOPAY_CPS_GEN_ORDER  " +
//                "  WHERE GOPAY_INT_TXN_CD IN ('02012', '02014', '02015','02020','02021') AND MER_REMARK2=:orderId");
//        map = new HashMap<>();
//        map.put("orderId", orderId);
//        int countAll = commonQueryDAO.findCountBySql(allSql.toString(), map);
//        if (countSuccess == countAll) {
//            return true;
//        }
//        LOGGER.error("赎回结算未全部成功,故订单状态不更新为成功,02018订单号为[{}]", orderId);
//        return false;
//    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void update02018OrderSuccess(String gopayOrderId) {
        operateDao.update02018OrderForSettle(gopayOrderId, FundSettleStatusEnum.SUCCESS_SETTLE.getValue(), TxnStaCode.TXN_STA_CD_20000.value);
    }

//    @Override
//    public boolean queryExistInnerTransferRedeemOrder() {
//        Map<String, Object> map = new HashMap<>();
//        map.put("settleDay", DateUtils.format(new Date(), "yyyyMMdd"));
//        int countBySql = commonQueryDAO.findCountBySql("  SELECT count(1) " +
//                "  FROM FUND_GOPAY_CPS_GEN_ORDER  " +
//                "  WHERE GOPAY_INT_TXN_CD IN ('02014', '02015') AND ORDER_TYPE ='23' AND MEMO IN ('01','02') AND STLM_DATE = to_date(:settleDay,'yyyyMMddHH24miss') ", map);
//        if (0 == countBySql) return false;
//        return true;
//    }

//    @Override
//    public void update02018OrderFail(String gopayOrderId) {
//        operateDao.update02018OrderForSettle(gopayOrderId, FundSettleStatusEnum.PAY_FAILURE.getValue(), TxnStaCode.TXN_STA_CD_20002.value, null);
//    }

//    @Override
//    public List<FundGopayCpsGenOrder> checkRedeemOrder(String gopayId) {
//        List<FundGopayCpsGenOrder> redeemIds = new ArrayList<>();
//        StringBuffer sb = new StringBuffer();
//        sb.append("SELECT TOTAL_ORDER_AMT,TOTAL_ORDER_FEE_AMT,GOPAY_ORDER_ID,ORDER_TYPE,GOPAY_INT_TXN_CD FROM FUND_GOPAY_CPS_GEN_ORDER " +
//                "WHERE MER_REMARK2=:gopayId AND GOPAY_INT_TXN_CD in ('02014','02015') ");
//        Map<String, Object> map = new HashMap<>();
//        map.put("gopayId", gopayId);
//        List<Object[]> rsList = commonQueryDAO.findBySql(sb.toString(), map);
//        if (rsList != null && rsList.size() > 0) {
//            for (Object[] obj : rsList) {
//                if (null == obj[0] || null == obj[1] || null == obj[2] || null == obj[3] || null == obj[4]) {
//                    continue;
//                }
//                String redeemId = obj[2].toString();
//                String orderType = obj[3].toString();
//                if (FundSettleStatusEnum.NEED_SETTLE.getValue().equals(orderType)) {
//                    //证明console发cps中断,重新发起任务
//                    LOGGER.info("基金订单因为console发往cps中断,重新尝试连接===========================" + redeemId);
//                    FundGopayCpsGenOrder cpsGenOrder = new FundGopayCpsGenOrder();
//                    cpsGenOrder.setGopayOrderId(redeemId);
//                    cpsGenOrder.setGopayIntTxnCd(obj[4].toString());
//                    cpsGenOrder.setTotalOrderAmt(new BigDecimal(obj[0].toString()));
//                    redeemIds.add(cpsGenOrder);
//                    continue;
//                }
//                StringBuffer mainSql = new StringBuffer("SELECT TXN_STA_CD,GOPAY_INT_TXN_CD FROM CPS_GEN_MAIN_ORDER WHERE GOPAY_ORDER_ID=" + redeemId);
//                List<Object[]> mainList = commonQueryDAO.findBySql(mainSql.toString());
//                if (mainList != null && mainList.size() == 1) {
//                    Object[] main = mainList.get(0);
//                    if (null == main[0] || null == main[1]) {
//                        continue;
//                    }
//                    int txnStaCd = Integer.parseInt(main[0].toString());
//                    String intTxnCd = main[1].toString();
//                    if (FundSettleStatusEnum.SUCCESS_SETTLE.getValue().equals(orderType) || TxnStaCode.TXN_STA_CD_20000.value == txnStaCd) {
//                        continue;
//                    }
//                    StringBuffer acctSql = new StringBuffer("SELECT PSTD_FLG,DR_CR,TRAN_AMT FROM ACPS_ACCT_TRANS_DTL WHERE GOPAY_ORDER_ID=" + redeemId);
//                    List<Object[]> acctList = commonQueryDAO.findBySql(acctSql.toString());
//                    if (acctList != null && acctList.size() > 0) {
//                        BigDecimal money = new BigDecimal("0");
//                        for (Object[] acct : acctList) {
//                            if (null == acct[0] || null == acct[1] || null == acct[2]) {
//                                continue;
//                            }
//                            String flag = acct[0].toString();
//                            String dr_cr = acct[1].toString();
//                            String amt = acct[2].toString();
//                            if ("Y".equals(flag) && "D".equals(dr_cr)) {
//                                money = money.add(new BigDecimal(amt));
//                            }
//                        }
//                        if (new BigDecimal(obj[0].toString()).add(new BigDecimal(obj[1].toString())).setScale(3).equals(money.setScale(3))) {
//                            if (IntTxnCd._02015.value.equals(intTxnCd)) {
//                                operateDao.update02018OrderForSettle(redeemId, FundSettleStatusEnum.SUCCESS_SETTLE.getValue(), TxnStaCode.TXN_STA_CD_20000.value, AccountingPoint._02015_APPLY.value);
//                            } else if (IntTxnCd._02014.value.equals(intTxnCd)) {
//                                operateDao.update02018OrderForSettle(redeemId, FundSettleStatusEnum.SUCCESS_SETTLE.getValue(), TxnStaCode.TXN_STA_CD_20000.value, AccountingPoint._02014_APPLY.value);
//                            }
//                        }
//                    }
//                }
//            }
//        }
//        return redeemIds;
//    }

    @Override
    public List<String> pullFileFromSftp(String settleDay) {
        //TODO 多家基金公司时候,此处要改造
        List<String> custIds = new ArrayList<>();
        List<String> allFundCorp = queryAllFundCorp();
        LOGGER.info("【赎回文件落地】已开通的基金公司有：{}", FastJsonUtil.toJSONString(allFundCorp));
        for (String custId : allFundCorp) {
            Map<String, Object> paraMap = new HashMap<>(2);
            paraMap.put("custId", custId);
            paraMap.put("itemKey", CustCorpInfoConstants.ITEM_KEY_FUNDORGNO);
            StringBuffer sql = new StringBuffer();
            sql.append("SELECT ITEM_VALUE,CUST_ID FROM CUST_INFO_EXTEND_ITEM WHERE CUST_ID =:custId AND ITEM_KEY =:itemKey");
            List<Object[]> org = commonQueryDAO.findBySql(sql.toString(), paraMap);
            if (org == null || org.size() != 1) {
                LOGGER.info("【赎回文件落地】根据custId未获取基金公司编码，查询返回结果为：{}", FastJsonUtil.toJSONString(org));
            }
            Map<String, Object> fileParaMap = new HashMap<>(1);
            Object[] fundCorp = org.get(0);
            //fileName rtfund_redeem_20171110
            fileParaMap.put("fileName", fundCorp[0].toString() + FundFileTypeEnum.SUPERVISE_REDEEM.getFileSuffix() + settleDay);
            List<Object[]> fileList =
                    commonQueryDAO.findBySql("SELECT KEY_ID,FILE_STATUS,FILE_PATH,FILE_NAME FROM FUND_GOPAY_FILE WHERE FILE_NAME=:fileName", fileParaMap);
            FundGopayFileEntity fileEntity = new FundGopayFileEntity();
            if (fileList != null && fileList.size() == 1) {
                Object[] objects = fileList.get(0);
                if ("2".equals(objects[1].toString())) {
                    LOGGER.info("【赎回文件落地】文件未落地，开始执行落地，CustId为：{}", custId);
                    if (objects[2] == null) {
                        fileEntity.setKeyId(objects[0].toString());
                        fileEntity.setFileStatus(objects[1].toString());
                        // supervise-redeem/rtfund/20171110
                        fileEntity.setFilePath(FundFilePathEnum.FUND_REDEEM_PATH.getValue() + fundCorp[0].toString() + "/" + settleDay);
                        fileEntity.setFileName(fileParaMap.get("fileName").toString());
                        fileEntity.setFileType(FundFileTypeEnum.SUPERVISE_REDEEM.getValue());
                        try {
                            boolean flag = pullFileFromSftp(fileEntity, settleDay, fundCorp[0].toString());
                            if (flag) {
                                LOGGER.info("【赎回文件落地】赎回文件获取,更新[{}]文件路径开始", custId);
                                operateDao.updateFile(fileEntity);
                                LOGGER.info("【赎回文件落地】赎回文件获取,更新[{}]文件路径结束", custId);
                                custIds.add(custId);
                            }
                        } catch (Exception e) {
                            LOGGER.error("【赎回文件落地】文件更新失败/或sftp关闭异常", fundCorp[0].toString(), e);
                        }
                    } else {
                        custIds.add(custId);
                        LOGGER.info("【赎回文件落地】sftp服务器文件已验证，且无需更新文件表（FUND_GOPAY_FILE），直接将该用户（{}）返回以进行下一步操作。", custId);
                    }
                } else {
                    LOGGER.info("【赎回文件落地】赎回获取文件=====文件状态为1,文件已入库,终止执行[{}]获取文件逻辑", custId);
                }
            } else {
                if (fileList == null || fileList.size() == 0) {
                    LOGGER.info("【赎回文件落地】赎回获取文件,因数据库文件模板未创建,故创建[{}]文件模板开始", fileParaMap.get("fileName").toString());
                    fileEntity.setKeyId(UUID.randomUUID().toString().replace("-", ""));
                    fileEntity.setCustId(custId);
                    fileEntity.setFileName(fileParaMap.get("fileName").toString());
                    fileEntity.setFileStatus("2");
                    fileEntity.setSettleTime(DateUtils.strToDate(settleDay, "yyyyMMdd"));
                    fileEntity.setCreatedTs(new Date());
                    fileEntity.setLastUpdTs(new Date());
                    fileEntity.setSource("p");
                    fileEntity.setVersion(0);
                    fileEntity.setTotalAmount(new BigDecimal(0));
                    fileEntity.setTotalSum(0);
                    fundFileDao.saveFile(fileEntity);
                    LOGGER.info("【赎回文件落地】赎回获取文件,因数据库文件模板未创建,故创建[{}]文件模板结束", fileParaMap.get("fileName").toString());
                }
            }
        }
        LOGGER.info("【赎回文件落地】操作结果，需要反馈的基金公司有：{}", FastJsonUtil.toJSONString(custIds));
        return custIds;
    }

    /**
     * 将sftp服务器上的文件，拉取到本地
     *
     * @param redeemFile       :
     * @param settleDay        :
     * @param organizationCode :
     * @return boolean
     * @author dong-wang5@hnair.com
     * @date 2017-11-10 14:27:51
     * @params
     */
    private boolean pullFileFromSftp(FundGopayFileEntity redeemFile, String settleDay, String organizationCode) throws Exception {
        boolean flag = false;
        String filePath = redeemFile.getFilePath();
        if (!FundFilePathEnum.FUND_FTP_ROOT_PATH.getValue().contains(filePath)) {
            filePath = FundFilePathEnum.FUND_FTP_ROOT_PATH.getValue() + filePath;
        }
        String fileName;
        if (redeemFile.getFileName().endsWith(".txt")) {
            fileName = redeemFile.getFileName().replace(" ", "");
        } else {
            fileName = (redeemFile.getFileName().replace(" ", "") + ".txt");
        }
        String saveName;
        String property = "/usr/local/ciecc/webapps/upload/fund/tmp";
        String str = property + "/" + organizationCode + "/" + settleDay;

        File file = new File(str);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (mkdirs) {
                LOGGER.info("【赎回文件落地】临时目录创建成功！目录：{}", str);
            } else {
                LOGGER.info("【赎回文件落地】临时目录创建失败！目录：{}", str);
                return false;
            }
        }
        saveName = str + "/" + fileName;
        LOGGER.info("【赎回文件落地】开始连接SFTP服务器，文件名：{}，临时文件目录：{}，sftp服务器路径：{}", new Object[]{fileName, str, filePath});
        try {
            boolean download = SftpUtil.download(IP, PORT, USERNAME, PASSWORD, TIMEOUT, filePath, fileName, str);
            if (download) {
                List<ArrayList<String>> arrayLists = ReadFundZipUtils.readTxt(bundle.getString("FTPCHARSET"), saveName);
                if (arrayLists != null && arrayLists.size() > 0) {
                    flag = true;
                }
            } else {
                LOGGER.error("【赎回文件落地】未获取到ftp文件！");
            }
        } catch (Exception e) {
            LOGGER.error("赎回文件获取[{}]连接sftp异常", redeemFile.getFileName(), e);
        } finally {
            LOGGER.info("赎回文件获取[{}]连接sftp结束", redeemFile.getFileName());
            if (file != null) {
                file.delete();
            }
        }
        return flag;
    }
}
